package jnpf.base.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jnpf.base.entity.VisualdevEntity;
import jnpf.base.mapper.VisualdevMapper;
import jnpf.base.model.VisualWebTypeEnum;
import jnpf.base.service.DictionaryDataService;
import jnpf.base.service.VisualdevService;
import jnpf.base.model.PaginationVisualdev;
import jnpf.engine.entity.FlowEngineEntity;
import jnpf.engine.service.FlowEngineService;
import jnpf.engine.util.ConcurrencyUtils;
import jnpf.engine.util.VisualTableModel;
import jnpf.model.visiual.*;
import jnpf.engine.util.VisualDevTableCre;
import jnpf.exception.WorkFlowException;
import jnpf.model.FormAllModel;
import jnpf.model.visiual.fields.FieLdsModel;
import jnpf.util.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author JNPF开发平台组
 * @version V3.1.0
 * @copyright 引迈信息技术有限公司（https://www.jnpfsoft.com）
 * @date 2021/3/16
 */
@Service
public class VisualdevServiceImpl extends ServiceImpl<VisualdevMapper, VisualdevEntity> implements VisualdevService {

    @Autowired
    private FlowEngineService flowEngineService;
    @Autowired
    private DictionaryDataService dictionaryDataService;
    @Autowired
    private UserProvider userProvider;
    @Autowired
    private VisualDevTableCre visualDevTableCre;
    @Autowired
    private ConcurrencyUtils concurrencyUtils;

    @Override
    public List<VisualdevEntity> getList(PaginationVisualdev paginationVisualdev) {
        // 定义变量判断是否需要使用修改时间倒序
        boolean flag = false;
        QueryWrapper<VisualdevEntity> queryWrapper = new QueryWrapper<>();
        if (!StringUtil.isEmpty(paginationVisualdev.getKeyword())) {
            flag = true;
            queryWrapper.lambda().like(VisualdevEntity::getFullName, paginationVisualdev.getKeyword());
        }
        queryWrapper.lambda().eq(VisualdevEntity::getType, paginationVisualdev.getType());
        if (StringUtil.isNotEmpty(paginationVisualdev.getCategory())){
            flag = true;
            queryWrapper.lambda().eq(VisualdevEntity::getCategory, paginationVisualdev.getCategory());
        }
        // 排序
        queryWrapper.lambda().orderByAsc(VisualdevEntity::getSortCode).orderByDesc(VisualdevEntity::getCreatorTime);
        if (flag) {
            queryWrapper.lambda().orderByDesc(VisualdevEntity::getLastModifyTime);
        }
        Page<VisualdevEntity> page = new Page<>(paginationVisualdev.getCurrentPage(), paginationVisualdev.getPageSize());
        IPage<VisualdevEntity> userPage = this.page(page, queryWrapper);
        return paginationVisualdev.setData(userPage.getRecords(), page.getTotal());
    }


    @Override
    public List<VisualdevEntity> getList() {
        QueryWrapper<VisualdevEntity> queryWrapper = new QueryWrapper<>();
        // 排序
        queryWrapper.lambda().orderByAsc(VisualdevEntity::getSortCode).orderByDesc(VisualdevEntity::getCreatorTime);
        return this.list(queryWrapper);
    }

    @Override
    public VisualdevEntity getInfo(String id) {
        QueryWrapper<VisualdevEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(VisualdevEntity::getId, id);
        return this.getOne(queryWrapper);
    }

    @Override
    public Boolean create(VisualdevEntity entity) throws WorkFlowException {
        if (StringUtil.isEmpty(entity.getId())){
            entity.setId(RandomUtil.uuId());
        }

        FormDataModel formDataModel = JsonUtil.getJsonToBean(entity.getFormData(), FormDataModel.class);
        //是否开启安全锁
        Boolean concurrencyLock = formDataModel.getConcurrencyLock();
        int primaryKeyPolicy = formDataModel.getPrimaryKeyPolicy();

        //判断是否要创表
        List<TableModel> tableModels = JsonUtil.getJsonToList(entity.getVisualTables(), TableModel.class);
        Map<String, Object> formMap = JsonUtil.stringToMap(entity.getFormData());
        //无表需要创表
        if (tableModels.size()==0){
            List<FieLdsModel> list = JsonUtil.getJsonToList(formMap.get("fields"), FieLdsModel.class);
            JSONArray formJsonArray = JsonUtil.getJsonToJsonArray(String.valueOf(formMap.get("fields")));

            List<FormAllModel> formAllModel = new ArrayList<>();
            RecursionForm recursionForm = new RecursionForm();
            recursionForm.setTableModelList(JsonUtil.getJsonToList(entity.getVisualTables(), TableModel.class));
            recursionForm.setList(list);
            FormCloumnUtil.recursionForm(recursionForm, formAllModel);

            String tableName ="mt"+ RandomUtil.uuId();

            String dbLinkId = entity.getDbLinkId();
            VisualTableModel model = new VisualTableModel(formJsonArray, formAllModel, tableName, dbLinkId,entity.getFullName(),concurrencyLock,primaryKeyPolicy);
            List<TableModel> tableModelList = visualDevTableCre.tableList(model);

            formMap.put("fields",formJsonArray);
            //更新
            entity.setFormData(JsonUtil.getObjectToString(formMap));
            entity.setVisualTables(JsonUtil.getObjectToString(tableModelList));
        }else {
            List<TableModel> visualTables = JsonUtil.getJsonToList(entity.getVisualTables(), TableModel.class);
            TableModel mainTable = visualTables.stream().filter(f -> f.getTypeId().equals("1")).findFirst().orElse(null);
            //是否开启安全锁
                //在主表创建锁字段
                try {
                    if (concurrencyLock) {
                        concurrencyUtils.createVersion(mainTable.getTable(), entity.getDbLinkId());
                    }
                    if (primaryKeyPolicy==2){
                        concurrencyUtils.createFlowTaskId(mainTable.getTable(),entity.getDbLinkId());
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                    System.out.println("创建锁字段失败");
                    e.printStackTrace();
                }
        }
        entity.setCreatorUser(userProvider.get().getUserId());
        entity.setSortCode(RandomUtil.parses());
        if (ObjectUtil.isNotEmpty(entity.getWebType()) && VisualWebTypeEnum.FLOW_FROM.getType().equals(entity.getWebType())){
            entity.setFlowId(entity.getId());
            if (entity.getType().equals(1) || entity.getType().equals(2)){
                FlowEngineEntity flowEngineEntity = new FlowEngineEntity();
                flowEngineEntity.setId(entity.getId());
                flowEngineEntity.setFlowTemplateJson(entity.getFlowTemplateJson());
                flowEngineEntity.setEnCode("visualDev"+entity.getEnCode());
                flowEngineEntity.setType(1);
                flowEngineEntity.setIcon("icon-ym icon-ym-node");
                flowEngineEntity.setIconBackground("#008cff");
                flowEngineEntity.setEnabledMark(1);
                flowEngineEntity.setFullName(entity.getFullName());
                flowEngineEntity.setCategory(dictionaryDataService.getInfo(entity.getCategory()).getEnCode());
                flowEngineEntity.setFormType(2);
                flowEngineEntity.setFlowTables(entity.getVisualTables());
                flowEngineEntity.setDbLinkId(entity.getDbLinkId());
                flowEngineEntity.setFormData(entity.getFormData());
                flowEngineService.create(flowEngineEntity);
                entity.setFlowId(flowEngineEntity.getId());
            }
        }
         return this.save(entity);
    }

    @Override
    public boolean update(String id, VisualdevEntity entity) throws Exception {
        entity.setId(id);
        entity.setLastModifyUser(userProvider.get().getUserId());

        FormDataModel formDataModel = JsonUtil.getJsonToBean(entity.getFormData(), FormDataModel.class);
        List<TableModel> visualTables = JsonUtil.getJsonToList(entity.getVisualTables(), TableModel.class);
        TableModel mainTable = visualTables.stream().filter(f -> f.getTypeId().equals("1")).findFirst().orElse(null);

        //是否开启安全锁
        Boolean concurrencyLock = formDataModel.getConcurrencyLock();
        if (concurrencyLock){
            //在主表创建锁字段
            concurrencyUtils.createVersion(mainTable.getTable(),entity.getDbLinkId());
        }
        if (formDataModel.getPrimaryKeyPolicy()==2){
            concurrencyUtils.createFlowTaskId(mainTable.getTable(),entity.getDbLinkId());
        }
        //关联流程更新
        if (entity.getWebType() != null && VisualWebTypeEnum.FLOW_FROM.getType().equals(entity.getWebType())) {
            FlowEngineEntity flowEngineEntity = flowEngineService.getById(id);
            VisualdevEntity visualdevEntity = this.getInfo(id);
            //判断是否关联流程id
            if (visualdevEntity.getFlowId() == null) {
                entity.setFlowId(id);
            }
            //代码生成器 不生成流程引擎
            if (entity.getType().equals(1) || entity.getType().equals(2)) {
                    if (flowEngineEntity==null){
                        flowEngineEntity = new FlowEngineEntity();
                        flowEngineEntity.setId(id);
                        flowEngineEntity.setFlowTemplateJson(entity.getFlowTemplateJson());
                        flowEngineEntity.setEnCode("visualDev" + entity.getEnCode());
                        flowEngineEntity.setType(1);
                        flowEngineEntity.setIcon("icon-ym icon-ym-node");
                        flowEngineEntity.setIconBackground("#008cff");
                        flowEngineEntity.setEnabledMark(1);
                        flowEngineEntity.setFormType(2);
                        flowEngineEntity.setFlowTables(entity.getVisualTables());
                        flowEngineEntity.setDbLinkId(entity.getDbLinkId());
                        flowEngineEntity.setFormData(entity.getFormData());
                        flowEngineEntity.setFullName(entity.getFullName());
                        flowEngineService.create(flowEngineEntity);
                    }
                    flowEngineEntity.setFullName(entity.getFullName());
                    flowEngineEntity.setFlowTemplateJson(entity.getFlowTemplateJson());
                    flowEngineEntity.setFlowTables(entity.getVisualTables());
                    flowEngineEntity.setDbLinkId(entity.getDbLinkId());
                    flowEngineEntity.setFormData(entity.getFormData());
                    flowEngineService.update(visualdevEntity.getId(), flowEngineEntity);
            }
        }
        return this.updateById(entity);
    }

    @Override
    public void delete(VisualdevEntity entity) throws WorkFlowException {
        if (entity != null) {
            if(StringUtil.isNotEmpty(entity.getFlowId())){
                FlowEngineEntity flowEngineEntity = flowEngineService.getById(entity.getFlowId());
                if (flowEngineEntity!=null){
                    flowEngineService.delete(flowEngineEntity);
                }
            }
            this.removeById(entity.getId());
        }
    }

    @Override
    public Long getObjByEncode(String encode, Integer type) {
        QueryWrapper<VisualdevEntity> visualWrapper = new QueryWrapper<>();
        visualWrapper.lambda().eq(VisualdevEntity::getEnCode,encode).eq(VisualdevEntity::getType,type);
        Long count = this.baseMapper.selectCount(visualWrapper);
        return count;
    }

    @Override
    public Long getCountByName (String name, Integer type) {
        QueryWrapper<VisualdevEntity> visualWrapper = new QueryWrapper<>();
        visualWrapper.lambda().eq(VisualdevEntity::getFullName,name).eq(VisualdevEntity::getType,type);
        Long count = this.baseMapper.selectCount(visualWrapper);
       return count;
    }

    @Override
    public Map<String,String> getTableNameToKey(String modelId){
        Map<String,String> childKeyMap = new HashMap<>();
        VisualdevEntity info = this.getInfo(modelId);
        FormDataModel formDataModel = JsonUtil.getJsonToBean(info.getFormData(), FormDataModel.class);
        List<FieLdsModel> fieLdsModels = JsonUtil.getJsonToList(formDataModel.getFields(), FieLdsModel.class);
        List<FieLdsModel> childFields = fieLdsModels.stream().filter(f -> JnpfKeyConsts.CHILD_TABLE.equals(f.getConfig().getJnpfKey())).collect(Collectors.toList());
        childFields.stream().forEach(c->
            childKeyMap.put(c.getConfig().getTableName().toLowerCase(),c.getVModel())
        );
        return childKeyMap;
    }
}
